﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.IO;

namespace com.tiyma.components
{
    public class BCPManager
    {
        const string m_t = "#";
        const string m_r = "%$";

        /// <summary>
        /// 导出数据
        /// </summary>
        /// <returns></returns>
        public string ExportData()
        {
            try
            {
                SysConfig t_config = SerializationHelper.Load(typeof(SysConfig), "") as SysConfig;

                if (t_config == null)
                {
                    LogHelper.Debug("加载配置文件失败");
                    return "加载配置文件失败";
                }

                //链接数据库字符串
                string t_conn_str = string.Format("Data Source={0};Initial Catalog={1};User ID={2};Password={3}", t_config.DBServer,
                    t_config.DataBaseName,
                    t_config.DBUserName, AES.DecryptString(t_config.DBPassword));

                string t_bcp_command = string.Empty;

                StringBuilder t_sb = new StringBuilder();

                string[] t_table_name_arr = t_config.TableName.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

                if (t_table_name_arr == null || t_table_name_arr.Length <= 0)
                    return "配置的表不存在";

                string t_ret = string.Empty;
                string t_str_sql = string.Empty;

                foreach (string t_table in t_table_name_arr)
                {


                    t_bcp_command = string.Format("bcp \"select  * from {0}.dbo.{1}\" queryout \"{2}\\{1}_{3}.txt\" -S\"{4}\" -U\"{5}\" -P\"{6}\" -c -t\"{7}\" -r\"{8}\" -k -b5000 -a65535", t_config.DataBaseName, t_table, t_config.FilePath, DateTime.Now.ToString("yyyyMMddHHmmss"), t_config.DBServer, t_config.DBUserName, AES.DecryptString(t_config.DBPassword),m_t,m_r);

                    t_ret = RunCmd(t_bcp_command);
                    t_sb.Append(t_ret);
                }

                LogHelper.Info(t_sb.ToString());

                return t_sb.ToString();

            }
            catch (Exception ex)
            {
                LogHelper.Error("执行cmd命令导出数据失败" + ex.ToString());
                return "导出出现异常";
            }
        }

        /// <summary>
        /// 服务调用
        /// </summary>
        public void ImportDataByService()
        {
            while (true)
            {
                System.Threading.Thread.Sleep(100);

                ImportData();

                System.Threading.Thread.Sleep(AppConfig.ImportInterval*60*1000);
            }
        }

        /// <summary>
        /// 手动点击导入功能
        /// </summary>
        /// <returns></returns>
        public string ImportDataByClick()
        {
            try
            {
                SysConfig t_config = SerializationHelper.Load(typeof(SysConfig), "") as SysConfig;

                if (t_config == null)
                {
                    LogHelper.Debug("加载配置文件失败");
                    return "加载配置文件失败";
                }

                System.IO.DirectoryInfo t_dir = new System.IO.DirectoryInfo(t_config.FilePath);

                List<System.IO.FileInfo> t_list = new List<System.IO.FileInfo>();

                foreach (System.IO.FileInfo t_file in t_dir.GetFiles(string.Format("{0}-*-data.txt",t_config.TableName)))
                {
                    t_list.Add(t_file);
                }

                if (t_list == null || t_list.Count <= 0)
                    return "没有需要导入的文件!";

                string t_bcp_command = string.Empty;
                StringBuilder t_sb = new StringBuilder();
                string t_ret = string.Empty;
                string t_file_name = string.Empty;
                //链接数据库字符串
                string t_conn_str = string.Format("Data Source={0};Initial Catalog={1};User ID={2};Password={3}", t_config.DBServer,
                    t_config.DataBaseName,
                    t_config.DBUserName, AES.DecryptString(t_config.DBPassword));


                //创建备份目录
                string t_bak_path = System.IO.Path.Combine(t_dir.Parent.FullName, "book_chapter_bak");
                t_bak_path = System.IO.Path.Combine(t_dir.Parent.FullName, string.Format("data_{0}_bak", DateTime.Now.ToString("yyyyMM")));
                if (System.IO.Directory.Exists(t_bak_path) == false)
                {
                    System.IO.Directory.CreateDirectory(t_bak_path);
                }

                for (int index = 0; index < t_list.Count; index++)
                {
                    t_bcp_command = string.Format("bcp \"{0}.dbo.{1}\" in \"{2}\"  -t\"{6}\" -r\"{7}\" -c -S\"{3}\" -U\"{4}\" -P\"{5}\"  -m \"50000\" -b \"40000\" -a \"65535\"", t_config.DataBaseName, t_config.TableName, t_list[index].FullName, t_config.DBServer, t_config.DBUserName, AES.DecryptString(t_config.DBPassword), m_t, m_r);

                    t_ret = RunCmd(t_bcp_command);

                    if (CheckSuccess(t_ret))
                    {
                        if (!File.Exists(Path.Combine(t_bak_path, t_list[index].Name)))
                        {
                            //文件移动到备份目录
                            System.IO.File.Move(t_list[index].FullName, System.IO.Path.Combine(t_bak_path, t_list[index].Name));
                        }

                        t_file_name = t_list[index].Name.Replace("data", "sql");
                        string[] t_sql_line_arr = File.ReadAllLines(Path.Combine(t_config.FilePath, t_file_name), System.Text.Encoding.Default);

                        foreach (string t_sql in t_sql_line_arr)
                        {
                            DBManager.ExecuteSql(t_sql, t_conn_str);

                            System.Threading.Thread.Sleep(100);
                        }

                        if (!File.Exists(Path.Combine(t_bak_path, t_file_name)))
                        {
                            File.Move(Path.Combine(t_config.FilePath, t_file_name), Path.Combine(t_bak_path, t_file_name));
                        }


                    }

                    t_sb.Append(t_ret);
                }

                LogHelper.Info(t_sb.ToString());

                return t_sb.ToString();
            }
            catch (Exception ex)
            {
                LogHelper.Error("导入数据失败" + ex.ToString());
                return "导入数据发生异常";
            }
        }

        /// <summary>
        /// 导入数据
        /// </summary>
        /// <returns></returns>
        public string ImportData()
        {
            try
            {
                SysConfig t_config = SerializationHelper.Load(typeof(SysConfig), "") as SysConfig;

                if (t_config == null)
                {
                    LogHelper.Debug("加载配置文件失败");
                    return "加载配置文件失败";
                }

                System.IO.DirectoryInfo t_dir = new System.IO.DirectoryInfo(t_config.FilePath);

                List<System.IO.FileInfo> t_list = new List<System.IO.FileInfo>();

                foreach (System.IO.FileInfo t_file in t_dir.GetFiles("*-data.txt"))
                {
                    t_list.Add(t_file);
                }

                //按创建时间排序
                if (t_list != null && t_list.Count > 0)
                {
                    t_list.Sort(delegate(System.IO.FileInfo t_a, System.IO.FileInfo t_b)
                        {
                            if (t_a.CreationTime < t_b.CreationTime)
                                return -1;
                            else if (t_a.CreationTime == t_b.CreationTime)
                                return 0;
                            return 1;
                        });
                }

                string t_table_name = string.Empty;
                string t_bcp_command = string.Empty;
                StringBuilder t_sb = new StringBuilder();
                string t_ret = string.Empty;
                string t_file_name = string.Empty;
                //链接数据库字符串
                string t_conn_str = string.Format("Data Source={0};Initial Catalog={1};User ID={2};Password={3}", t_config.DBServer,
                    t_config.DataBaseName,
                    t_config.DBUserName, AES.DecryptString(t_config.DBPassword));
             
                int t_index = 0;

                Dictionary<string, int> t_dic = new Dictionary<string, int>();

                List<FileInfo> t_upload_list = new List<FileInfo>();

                for(int index=0;index<t_list.Count;index++)
                {
                    t_index = t_list[index].Name.IndexOf("-");

                    t_table_name = t_list[index].Name.Substring(0, t_index);

                    if (t_dic.ContainsKey(t_table_name))
                    {
                        t_upload_list.Add(t_list[index - 1]);
                    }
                    else
                    {
                        t_dic.Add(t_table_name, index);
                    }

                }


                //创建备份目录
                string t_bak_path = System.IO.Path.Combine(t_dir.Parent.FullName, "book_chapter_bak");
                t_bak_path = System.IO.Path.Combine(t_dir.Parent.FullName, string.Format("data_{0}_bak", DateTime.Now.ToString("yyyyMM")));
                if (System.IO.Directory.Exists(t_bak_path) == false)
                {
                    System.IO.Directory.CreateDirectory(t_bak_path);
                }

                for (int index = 0; index < t_upload_list.Count ; index++)
                {
                    t_index = t_upload_list[index].Name.IndexOf("-");

                    t_table_name = t_upload_list[index].Name.Substring(0, t_index);

                    t_bcp_command = string.Format("bcp \"{0}.dbo.{1}\" in \"{2}\"  -t\"{6}\" -r\"{7}\" -c -S\"{3}\" -U\"{4}\" -P\"{5}\"  -m \"50000\" -b \"40000\" -a \"65535\"", t_config.DataBaseName, t_table_name, t_upload_list[index].FullName, t_config.DBServer, t_config.DBUserName, AES.DecryptString(t_config.DBPassword), m_t, m_r);

                    t_ret = RunCmd(t_bcp_command);

                    if (CheckSuccess(t_ret))
                    {
                        if (!File.Exists(Path.Combine(t_bak_path, t_upload_list[index].Name)))
                        {
                            //文件移动到备份目录
                            System.IO.File.Move(t_upload_list[index].FullName, System.IO.Path.Combine(t_bak_path, t_upload_list[index].Name));
                        }

                        t_file_name = t_upload_list[index].Name.Replace("data", "sql");
                        string[] t_sql_line_arr=File.ReadAllLines(Path.Combine(t_config.FilePath, t_file_name),System.Text.Encoding.Default);

                        foreach (string t_sql in t_sql_line_arr)
                        {
                            DBManager.ExecuteSql(t_sql, t_conn_str);

                            System.Threading.Thread.Sleep(100);
                        }

                        if (!File.Exists(Path.Combine(t_bak_path, t_file_name)))
                        {
                            File.Move(Path.Combine(t_config.FilePath, t_file_name), Path.Combine(t_bak_path, t_file_name));
                        }
                         
                       
                    }

                    t_sb.Append(t_ret);
                }

                LogHelper.Info(t_sb.ToString());

                return t_sb.ToString();
            }
            catch (Exception ex)
            {
                LogHelper.Error("导入数据失败" + ex.ToString());
                return "导入数据发生异常";
            }

        }

        /// <summary>
        /// 检查导出是否成功
        /// </summary>
        /// <param name="i_ret"></param>
        /// <returns></returns>
        private bool CheckSuccess(string i_ret)
        {
            string t_regex = "已复制了\\s*?(\\d+)\\s*?行";
            Match t_mc = Regex.Match(i_ret, t_regex, RegexOptions.IgnoreCase | RegexOptions.Compiled);

            int t_row = 0;
            if (t_mc != null && t_mc.Groups.Count > 0)
            {
                if (!int.TryParse(t_mc.Groups[1].Value.ToString(), out t_row))
                    t_row = 0;
            }

            if (t_row > 0)
                return true;
            return false;
        }

        /// <summary>
        /// 执行cmd命令
        /// </summary>
        /// <param name="i_command"></param>
        /// <returns></returns>
        private string RunCmd(string i_command)
        {
            try
            {
                Process p = new Process();

                p.StartInfo.FileName = "cmd.exe";           //设定程序名
                p.StartInfo.Arguments = "/c " + i_command;    //设定程序执行参数
                p.StartInfo.UseShellExecute = false;        //关闭Shell的使用
                p.StartInfo.RedirectStandardInput = true;   //重定向标准输入
                p.StartInfo.RedirectStandardOutput = true;  //重定向标准输出
                p.StartInfo.RedirectStandardError = true;   //重定向错误输出
                p.StartInfo.CreateNoWindow = true;          //设置不显示窗口

                p.Start();   //启动

                return p.StandardOutput.ReadToEnd();        //输出执行结果
            }
            catch (Exception ex)
            {
                LogHelper.Error(string.Format("执行cmd命令：{0}失败", i_command) + ex.ToString());
                return string.Empty;
            }
        }
    }
}
